package DRCOMM;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class execTimeParser {

    public String monthExpress = "";
    public String dayExpress = "";
    public String weekDayExpress = "";
    public String hourExpress = "";
    public String minuteExpress = "";

    public execTimeParser(String execTimeStr) throws Exception{
        if(checkExecExpress(execTimeStr)){
            String[] execTime = execTimeStr.split(" ");
            this.minuteExpress=execTime[0];
            this.hourExpress=execTime[1];
            this.dayExpress=execTime[2];
            this.monthExpress=execTime[3];
            this.weekDayExpress=execTime[4];
        }else{
            throw new Exception("extcTimeParser fail!!");
        }
    }
    
    public static boolean checkExecExpress(String execExpress){
        boolean result=false;
        // 创建模式字符串
        String pattern = "^(((\\*|(\\*\\/[0-9]+)|[0-9]+-[0-9]+|[0-9]+),?)+ ){4}(((\\*|(\\*\\/[0-9]+)|[0-9]+-[0-9]+|[0-9]+),?)+)$";
        // 创建 Pattern 对象
        Pattern r = Pattern.compile(pattern);
        // 创建 matcher 对象
        Matcher m = r.matcher(execExpress);
        if(m.find()){
            result=true;
        }
        return result;
    }

    /**
     * 检查时间单位是否符合执行条件
     * @param timeUnit 时间单位
     * @param execStr 执行表达式
     * @return 符合条件返回真，否则返回假
     */
    public static boolean checkExecConditionExpress(int timeUnit,String execStr){
        boolean result=false;
        String[] execUnit = execStr.split(",");
        for(String exec:execUnit){
            if(exec.equals("*")){
                // 如果是 * ，则直接回复真
                return true;
            }else if(exec.length()>2&&exec.substring(0,2).equals("*/")){
                // 如果是 */ ，则需要判断是否能整除后面的数值
                if(timeUnit % Integer.parseInt(exec.substring(2))==0){
                    return true;
                }
            }else if(exec.indexOf("-")>0){
                int beginTime=Integer.parseInt(exec.substring(0, exec.indexOf("-")));
                int endTime=Integer.parseInt(exec.substring(exec.indexOf("-")+1));
                if(beginTime>endTime){
                    if(timeUnit >= beginTime&&timeUnit <= endTime)return true;
                }else{
                    if(timeUnit <= beginTime&&timeUnit >= endTime)return true;           
                }
            }else if(timeUnit==Integer.parseInt(exec)){
                return true;
            }
        }
        return result;
    }

    /**
     * 检测执行表达式及输入时间，只支持个表达式
     * 如果符合条件则返回真
     * 否则返回假
     * @param execTimeStr 执行表达式，格式参见crontab
     * @param inTime 时间，为""时为当前时间，格式为:yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static boolean checkExec(String execTimeStr,String inTime){
        boolean result=true;
        Date time=new Date();
        SimpleDateFormat ft=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(!inTime.equals("")){
            try {
                time=ft.parse(inTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        Calendar cal=Calendar.getInstance();
        cal.setTime(time);
        try {
            execTimeParser etp=new execTimeParser(execTimeStr);
            if(!checkExecConditionExpress(cal.get(Calendar.MINUTE),etp.minuteExpress))return false;
            if(!checkExecConditionExpress(cal.get(Calendar.HOUR_OF_DAY),etp.hourExpress))return false;
            if(!checkExecConditionExpress(cal.get(Calendar.DAY_OF_MONTH),etp.dayExpress))return false;
            if(!checkExecConditionExpress(cal.get(Calendar.MONTH)+1,etp.monthExpress))return false;
            if(!checkExecConditionExpress(cal.get(Calendar.DAY_OF_WEEK),etp.weekDayExpress))return false;
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 检测执行表达式及输入时间，允许使用";"分割多个表达式
     * 如果符合条件则返回真
     * 否则返回假
     * @param execTimeStr 执行表达式，格式参见crontab
     * @param inTime 时间，为""时为当前时间，格式为:yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static boolean CcheckExec(String execTimeStr,String inTime){
        boolean result=false;
        String[] expressions=execTimeStr.split(";");
        for(String expression:expressions){
            if(checkExec(expression,inTime))return true;
        }
        return result;
    }

    public static void main(String[] args){
        System.out.println(execTimeParser.CcheckExec("* * * * *;44 14 * * *", ""));
    }
}
